﻿using UnityEngine;
using System.Collections;

public class BM_CollectableToy : BM_BaseToy
{
	public enum Action
	{
		ACTION_NONE = -1
	,	ACTION_LEFTHAND
	,	ACTION_RIGHTHAND
	,	ACTION_HEAD
	}


	#region Members

	// parametri da configurare tramite i prefab
	public Action		ActiveAction = Action.ACTION_NONE;
	public Transform	selectCollider;

	private Action		m_eIdleAction = Action.ACTION_RIGHTHAND; 

	private Vector3		m_vTargetPos = Vector3.zero;
	private Quaternion	m_qTargetRotation = Quaternion.identity;

	private Transform	m_rOriginalParent = null;

	private float		m_fGrabSpeed = 5.0f;

	private static int	m_collectedToys = 0;
	private Vector3		m_vRealStartPosition = Vector3.zero;
	private Vector3		m_vFakeStartPosition = Vector3.zero;
	private Quaternion	m_qRealStartRotation = Quaternion.identity;
	private Quaternion	m_qFakeStartRotation = Quaternion.identity;

	private AudioClip	m_rGrabAudioClip = null;
	private AudioClip	m_rDropAudioClip = null;

	private bool		m_bWalking = false;


	#endregion




	public override void Awake ()
	{
		base.Awake ();

		m_rFSM.AddState(new BM_FSM.StateInfo((int)State.STATE_IDLE, GetType()+".STATE_IDLE", InitializeIdleState, UpdateIdleState));
		m_rFSM.AddState(new BM_FSM.StateInfo((int)State.STATE_CUT, GetType()+".STATE_CUT", InitializeCutState, UpdateCutState));
		m_rFSM.AddState(new BM_FSM.StateInfo((int)State.STATE_ACTION, GetType()+".STATE_ACTION", InitializeActionState, UpdateActionState));
		m_rFSM.NextState = (int)State.STATE_IDLE;
		m_rFSM.DebugPrint = true;

		m_rOriginalParent = gameObject.transform.parent;

		m_collectedToys = 0;

		// IDLE: l'ggetto non è attivo, se il giocatore ci interagisce va direttamente nello stato ACTION
		// ACTIVE: l'oggetto è attivo, se il giocatore ci interagisce va allo stato CUT (si trasforma)
		// CUT: il gioco si ferma (il controller del giocatore è disattivato), l'oggetto in questione si trasforma, al termine dell'animazione passa allo stato ACTION
		// ACTION: l'ggetto viene raccolto, posizione e rotazione vengono interpolate per finire in mano al giocatore (si deve sapere su quale mano finirà l'oggetto)
		m_vRealStartPosition = RealObject.transform.localPosition;
		m_qRealStartRotation = RealObject.transform.localRotation;
		m_vFakeStartPosition = FakeObject.transform.localPosition;
		m_qFakeStartRotation = FakeObject.transform.localRotation;

		m_rGrabAudioClip = Resources.Load("sfx_grab") as AudioClip;
		m_rDropAudioClip = Resources.Load("sfx_drop") as AudioClip;
	}




	private void InitializeIdleState()
	{
		RealObject.animation.Stop();
		RealObject.transform.localPosition = m_vRealStartPosition;
		RealObject.transform.localRotation = m_qRealStartRotation;

		FakeObject.animation.Stop();
		FakeObject.transform.localPosition = m_vFakeStartPosition;
		FakeObject.transform.localRotation = m_qFakeStartRotation;

		gameObject.transform.parent = m_rOriginalParent;
		gameObject.rigidbody.isKinematic = false;

		RealObject.SetActive(true);
		FakeObject.SetActive(false);

		m_rCurrentObject = RealObject;

		m_bWalking = false;
	}

	private void UpdateIdleState()
	{
		if(MessageHandler.ReceivedMessageWithID(MessageID.MSGID_TOY_PERFORM_ACTION) != null && m_bSelectable)
		{
			if(m_bQuestActive)
				m_rFSM.NextState = (int)State.STATE_CUT;
			else
				m_rFSM.NextState = (int)State.STATE_ACTION;

			selectCollider.gameObject.SetActive(false);
		}
	}

	// l'oggetto è stato grabbato

	private void InitializeActionState()
	{
		gameObject.rigidbody.isKinematic = true;
		gameObject.transform.parent = GetPlayerMountPoint();

		if(m_bQuestActive) {
			MessageHandler.SendMessageToAllButMe(new BM_BaseMessage(MessageID.MSGID_TOY_ACQUIRED, MessageHandler));
			m_collectedToys++;

			if(m_collectedToys == 3) {
				m_rMessageHandler.SendMessageToAllButMe(new BM_QuestActivationMessage(MessageID.MSGID_QUEST_DRAGONSLAYER_ALL_WEAPONS, MessageHandler, true));
			} else  if(m_collectedToys > 3) {
				m_rMessageHandler.SendMessageToAllButMe(new BM_BaseMessage(MessageID.MSGID_TOY_PERFORM_DROP, MessageHandler));
			}
		}

		AudioSource.PlayClipAtPoint(m_rGrabAudioClip, Vector3.zero, 0.3f);

		PlayIdleAnimation();
	}
	
	private void UpdateActionState()
	{
		if(!BM_Utils.PointsAreClose(gameObject.transform.position, m_vTargetPos, 0.01f))
			gameObject.transform.localPosition = Vector3.Lerp(gameObject.transform.localPosition, m_vTargetPos, m_fGrabSpeed*Time.deltaTime);

		if(!Mathf.Approximately(Quaternion.Dot(gameObject.transform.rotation, m_qTargetRotation), 1.0f))
			gameObject.transform.localRotation = Quaternion.Slerp(gameObject.transform.localRotation, m_qTargetRotation, m_fGrabSpeed*Time.deltaTime);

		if(MessageHandler.ReceivedMessageWithID(MessageID.MSGID_TOY_PERFORM_DROP) != null) {
			m_rFSM.NextState = (int)State.STATE_IDLE;
			StartCoroutine(SetColliderActive());
			AudioSource.PlayClipAtPoint(m_rDropAudioClip, Vector3.zero, 0.4f);
			if(m_bQuestActive) {
				m_bSelectable = false;
			}
		}

		if(Mathf.Approximately(m_rPlayer.GetMovementDirection.magnitude, 0.0f))
		{
			if(m_bWalking)
				PlayIdleAnimation();
		}
		else
		{
			if(!m_bWalking)
				PlayWalkAnimation();
		}
	}

	private IEnumerator SetColliderActive() {
		yield return new WaitForSeconds(1);
		selectCollider.gameObject.SetActive(true);
	}

	private Transform GetPlayerMountPoint()
	{
		Action eAction = m_bQuestActive ? ActiveAction : m_eIdleAction;
		switch(eAction)
		{
		case Action.ACTION_LEFTHAND:
			return m_rPlayer.leftArm;
			
		default:
		case Action.ACTION_RIGHTHAND:
			return m_rPlayer.rightArm;
			
		case Action.ACTION_HEAD:
			return m_rPlayer.head;
		}
	}

	private void PlayIdleAnimation()
	{
		Action eAction = m_bQuestActive ? ActiveAction : m_eIdleAction;
		switch(eAction)
		{
		case Action.ACTION_LEFTHAND:
			m_rCurrentObject.animation.CrossFade("lefthand_idle");
			break;
			
		default:
		case Action.ACTION_RIGHTHAND:
			m_rCurrentObject.animation.CrossFade("righthand_idle");
			break;
			
		case Action.ACTION_HEAD:
			m_rCurrentObject.animation.Stop();
			break;
		}
		m_bWalking = false;
	}

	private void PlayWalkAnimation()
	{
		Action eAction = m_bQuestActive ? ActiveAction : m_eIdleAction;
		switch(eAction)
		{
		case Action.ACTION_LEFTHAND:
			m_rCurrentObject.animation.CrossFade("lefthand_walk");
			break;
			
		default:
		case Action.ACTION_RIGHTHAND:
			m_rCurrentObject.animation.CrossFade("righthand_walk");
			break;
			
		case Action.ACTION_HEAD:
			m_rCurrentObject.animation.Stop();
			break;
		}
		m_bWalking = true;
	}
}
